﻿using System;
using System.Linq;
using Myotragus.Data;
using Myotragus.Data.Containers;
using Myotragus.Data.Criteria;
using Myotragus.Data.Domain;
using Myotragus.Data.Metadata;
using Myotragus.Store.Model.Tests.Domain;
using NHibernate.SqlCommand;
using NHibernate.Transform;
using NUnit.Framework;

namespace Myotragus.Store.Model.Tests
{
  [TestFixture]
  class LocalizableAliasFixture
  {
    private IEntitiesContainer _entities;

    [SetUp]
    public void SetUp()
    {
      FixtureHelper.InitializeServices();
      FixtureHelper.InitializeEntities(new []{typeof(ILocalizableObject)});
      FixtureHelper.InitializeSession(new[] { typeof(ILocalizableObject) });
      _entities = FixtureHelper.Container.Resolve<IEntitiesContainer>();
    }

    [Test]
    public void LocalizableAliasTest()
    {
      AliasTest(FixtureHelper.Container.Resolve<ILocalizableAlias>(), 
        FixtureHelper.Container.Resolve<ILocalizableEntityProjector<ILocalizableObject>>(), 
        _entities.ResolveType(typeof(ILoadEntity<ILocalizableObject>)));
    }

    [Test]
    public void DefaultsLocalizableAliasTest()
    {
      AliasTest(FixtureHelper.Container.Resolve<IDefaultsLocalizableAlias>(),
        FixtureHelper.Container.Resolve<IDefaultsLocalizableEntityProjector<ILocalizableObject>>(),
        _entities.ResolveType(typeof(IDefaultsLoadEntity<ILocalizableObject>)));
    }

    private void AliasTest(ILocalizableAlias alias, IProjector projector, Type loadType)
    {
      var descriptor = FixtureHelper.Container.Resolve<ILocalizableEntityDescriptor<ILocalizableObject>>();
      var factory = FixtureHelper.Container.Resolve<ISessionFactoryAdapter>();

      var type = _entities.ResolveType(typeof(ILocalizableObject));

      using (var session = factory.OpenSession())
      {
        var criteria = session.CreateCriteria(loadType);
        foreach (var prop in descriptor.LocalizableProperties)
          alias.CreateAlias(criteria, prop, prop, JoinType.LeftOuterJoin, 10);
      
        criteria.SetProjection(projector.GetProjection(null));
        criteria.SetResultTransformer(Transformers.AliasToBean(type));

        var list = criteria.List().Cast<ILocalizableObject>().ToArray();
        Assert.IsNotEmpty(list);
      }
    }
  }
}
